/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package main.initiate;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import main.KBProcess.KnowledgeBase;
import main.NER.Trie.CandidateExtractor;
import main.NER.Trie.KBTrie;
import main.NER.Trie.NER_Candidate;

/**
 *
 * @author Isaac Osesina
 */
public class CandidateExtractor_Threaded implements Runnable{
    LinkedList<Job> targetQueue;
    LinkedHashMap<Job, List<NER_Candidate>> jobResults;
    UTEES_Index kbIndex;
    KnowledgeBase kb;
    KBTrie kbTrie;
    CandidateExtractor candidateExtractor;
    final Object lockObj = new Object();

    public CandidateExtractor_Threaded(KBTrie kbTrie) {
        if(kbTrie != null) {
            candidateExtractor = new CandidateExtractor(kbTrie);
        }
        init();
    }


    private void init() {
        targetQueue = new LinkedList<Job>();
        jobResults = new LinkedHashMap<Job, List<NER_Candidate>>();
    }

    private synchronized void doJob(Job job) {
        if(job==null) {
            return;
        }
        List<NER_Candidate> candidates = candidateExtractor.extractCandidates(job.inString, job.weightMethod);
        if(candidates != null)
        jobResults.put(job, candidates);
    }

    public synchronized List<NER_Candidate> getResults(String inString, String weightMethod){
        if(inString != null || weightMethod != null)
            return null;
        Job job = new Job(inString, weightMethod);        
        return jobResults.get(job);
    }

    public synchronized Map<String, List<NER_Candidate>> getResults(){
        Map<String, List<NER_Candidate>> out = null;
        if(jobResults != null) {
            out = new HashMap<String, List<NER_Candidate>>();
            for(Job job:jobResults.keySet()) {
                if(job != null) {
                    out.put(job.weightMethod, jobResults.get(job));
                    jobResults.remove(job);
                }
            }
        }
        return out;
    }

    private synchronized int queueRunJobs(Job job) {
        int queue = 0;
        boolean add = targetQueue.add(job);
        if(add)
            queue = 1;
        synchronized (lockObj) {
            lockObj.notify();
        }
        return queue;
    }

    public synchronized int submitJob(String inString, String weightMethod) {
        if(inString != null || weightMethod!= null)
            return -1;
        Job job = new Job(inString, weightMethod);
        return queueRunJobs(job);
    }

    public synchronized int activeThreadCount() {
        return Thread.activeCount();
    }
    

     @Override
	public void run() {
         boolean startThread = true;
         if(kbTrie == null) {
             startThread =false;
         }
        while(startThread) {

            if(!targetQueue.isEmpty()) {
                Job poll = targetQueue.poll();
                if(poll != null) {
                    doJob(poll);
                }
            }
            else {
                synchronized (lockObj) {
                    try {
                        lockObj.wait();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(CandidateExtractor_Threaded.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
            Thread.yield();
        }
     }

     private static class Job implements Comparable<Job> {
         String inString;
         String weightMethod;

        public Job(String inString, String weightMethod) {
            this.inString = inString;
            this.weightMethod = weightMethod;
        }

        @Override
		public int compareTo(Job j) {
			if (inString.toLowerCase() == j.inString.toLowerCase()
					&& weightMethod.toLowerCase() == j.weightMethod
							.toLowerCase()) {
				return 0;
			}
			
			return -1;
		}
     }
}
